import os
import re
import requests
from other import (
    check_and_install_dependencies,
    clean_filename,
    download_single_file,
    download_danmu,
    process_danmu,
    check_ffmpeg,
    convert_media,
    merge_media,
    save_video_info,
    get_video_comments,
    save_comments
)

# 初始化：检查依赖
check_and_install_dependencies()

def get_bilibili_video_info(bv_id):
    """获取视频基本信息（标题、UP主、CID等）"""
    url = f"https://api.bilibili.com/x/web-interface/view?bvid={bv_id}"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Referer": "https://www.bilibili.com/"
    }
    
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        response.encoding = 'utf-8'
        data = response.json()
        
        if data.get("code") != 0:
            print(f"❌ 获取视频信息失败: {data.get('message', '未知错误')}")
            return None
        return data["data"]
    except Exception as e:
        print(f"❌ 获取视频信息出错: {str(e)}")
        return None

def get_media_urls(bv_id, cid):
    """获取视频流和音频流的下载链接"""
    try:
        url = f"https://api.bilibili.com/x/player/playurl?bvid={bv_id}&cid={cid}&qn=80&fnval=16"
        
        # 替换为你的Cookie（登录B站后获取）
        cookie = "SESSDATA=你的SESSDATA值; bili_jct=你的bili_jct值"
        cookie = re.sub(r'[^\x20-\x7E]', '', cookie)  # 移除非ASCII字符
        
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            "Referer": "https://www.bilibili.com/",
            "Cookie": cookie.encode('latin-1', errors='ignore').decode('latin-1')
        }
        
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        response.encoding = 'utf-8'
        data = response.json()
        
        if data.get("code") != 0:
            print(f"❌ 获取下载链接失败: {data.get('message', '未知错误')}")
            return None, None
        
        video_url = None
        audio_url = None
        if "dash" in data["data"]:
            if "video" in data["data"]["dash"]:
                video_url = data["data"]["dash"]["video"][0]["baseUrl"]
            if "audio" in data["data"]["dash"]:
                audio_url = data["data"]["dash"]["audio"][0]["baseUrl"]
        elif "durl" in data["data"]:
            video_url = data["data"]["durl"][0]["url"]
        
        return video_url, audio_url
    except Exception as e:
        print(f"❌ 获取下载链接出错: {str(e)}")
        return None, None

def download_bilibili_video(video_url, save_dir='./bilibili_downloads'):
    """主函数：处理下载逻辑，支持短链接、弹幕、评论及组合操作"""
    try:
        # 处理b23.tv短链接（深度清理URL）
        if "b23.tv" in video_url:
            print("🔗 检测到b23.tv短链接，正在解析真实地址...")
            try:
                # 1. 清理输入中的空格、反斜杠等无效字符
                video_url = re.sub(r'[\s\\]', '', video_url)
                # 2. 发送请求获取跳转地址
                response = requests.get(video_url, allow_redirects=True, timeout=10)
                video_url = response.url
                # 3. 清理跳转后的URL（移除特殊字符）
                video_url = re.sub(r'[^\w:/\.\-?&=]', '', video_url)
                print(f"✅ 解析成功，真实地址：{video_url}")
            except Exception as e:
                print(f"❌ 解析短链接失败: {str(e)}")
                return
        
        # 提取BV号
        bv_match = re.search(r'BV[0-9A-Za-z]+', video_url)
        if not bv_match:
            print("❌ 无法从URL中提取BV号，请检查地址是否正确")
            return
        bv_id = bv_match.group()
        print(f"✅ 提取到BV号: {bv_id}")
        
        # 获取视频信息
        print("🔍 获取视频信息中...")
        info = get_bilibili_video_info(bv_id)
        if not info:
            return
        title = clean_filename(info['title'])
        owner = info['owner']['name']
        cid = info['cid']
        print(f"📌 视频标题: {title}")
        print(f"👤 UP主: {owner}")
        
        # 创建保存目录
        os.makedirs(save_dir, exist_ok=True)
        base_path = os.path.join(save_dir, title)
        info_path = f"{base_path}_info.json"
        
        # 保存视频信息（含关联文件路径）
        video_info = {
            "title": title,
            "up主": owner,
            "bv号": bv_id,
            "cid": cid,
            "视频地址": video_url,
            "发布时间": info.get('pubdate'),
            "播放量": info.get('stat', {}).get('view'),
            "弹幕文件": f"{base_path}_danmu.txt",
            "评论文件": f"{base_path}_comments.txt"
        }
        save_video_info(video_info, info_path)
        
        # 检查ffmpeg
        ffmpeg_available = check_ffmpeg()
        
        # 显示操作选项（支持组合指令）
        print("\n请选择操作（可输入数字组合，如'18'表示合并+下载弹幕）：")
        if ffmpeg_available:
            print("1 - 下载并合并音视频（推荐）")
            print("2 - 仅下载视频（转为MP4）")
            print("3 - 仅下载音频（转为MP3）")
            print("4 - 同时下载视频和音频（分别转为MP4/MP3）")
        else:
            print("2 - 仅下载视频（原始格式）")
            print("3 - 仅下载音频（原始格式）")
            print("4 - 同时下载视频和音频（原始格式）")
        print("附加功能：")
        print("8 - 同时获取弹幕")
        print("9 - 同时获取评论")
        choice = input("请输入选项: ").strip() or "1"
        
        # 判断附加功能需求
        need_danmu = '8' in choice
        need_comment = '9' in choice
        
        # 下载弹幕
        if need_danmu:
            print("\n📥 开始下载弹幕...")
            danmu_xml = f"{base_path}_danmu.xml"
            danmu_txt = f"{base_path}_danmu.txt"
            if download_danmu(bv_id, cid, danmu_xml):
                process_danmu(danmu_xml, danmu_txt)
            else:
                print("⚠️ 弹幕下载失败")
        
        # 获取评论
        if need_comment:
            print("\n📥 开始获取评论...")
            comment_path = f"{base_path}_comments.txt"
            comments = get_video_comments(bv_id, page=3)
            if comments:
                save_comments(comments, comment_path)
            else:
                print("⚠️ 评论获取失败")
                print("评论接口返回：", data)  # 调试用
        
        # 获取音视频链接
        print("\n🔗 获取音视频下载链接中...")
        video_url, audio_url = get_media_urls(bv_id, cid)
        if not video_url:
            print("❌ 未获取到视频链接，无法下载")
            return
        
        # 处理音视频合一格式
        if not audio_url:
            print("📌 检测到音视频合一格式，直接下载...")
            video_path = f"{base_path}.mp4"
            download_single_file(video_url, video_path, "下载完整视频")
            return
        
        # 提取核心操作指令（过滤8/9）
        core_choice = re.sub(r'[89]', '', choice) or ("1" if ffmpeg_available else "2")
        
        # 执行音视频操作
        temp_video = f"{base_path}_temp_video"
        temp_audio = f"{base_path}_temp_audio"
        video_path = f"{base_path}.mp4"
        audio_path = f"{base_path}.mp3"
        merged_path = f"{base_path}.mp4"
        
        if core_choice == "1" and ffmpeg_available:
            print("\n📥 下载视频...")
            if not download_single_file(video_url, temp_video, "下载视频"):
                return
            print("\n📥 下载音频...")
            if not download_single_file(audio_url, temp_audio, "下载音频"):
                return
            print("\n🔗 合并音视频...")
            if merge_media(temp_video, temp_audio, merged_path):
                os.remove(temp_video)
                os.remove(temp_audio)
        
        elif core_choice == "2":
            print("\n📥 下载视频...")
            if ffmpeg_available:
                if download_single_file(video_url, temp_video, "下载视频"):
                    print("🔄 转换为MP4...")
                    convert_media(temp_video, video_path, 'video')
                    os.remove(temp_video)
            else:
                download_single_file(video_url, video_path, "下载视频")
        
        elif core_choice == "3":
            print("\n📥 下载音频...")
            if ffmpeg_available:
                if download_single_file(audio_url, temp_audio, "下载音频"):
                    print("🔄 转换为MP3...")
                    convert_media(temp_audio, audio_path, 'audio')
                    os.remove(temp_audio)
            else:
                audio_path = f"{base_path}.m4a"
                download_single_file(audio_url, audio_path, "下载音频")
        
        elif core_choice == "4":
            print("\n📥 下载视频...")
            if ffmpeg_available:
                if download_single_file(video_url, temp_video, "下载视频"):
                    print("🔄 转换为MP4...")
                    convert_media(temp_video, video_path, 'video')
                    os.remove(temp_video)
            else:
                download_single_file(video_url, video_path, "下载视频")
            
            print("\n📥 下载音频...")
            if ffmpeg_available:
                if download_single_file(audio_url, temp_audio, "下载音频"):
                    print("🔄 转换为MP3...")
                    convert_media(temp_audio, audio_path, 'audio')
                    os.remove(temp_audio)
            else:
                audio_path = f"{base_path}.m4a"
                download_single_file(audio_url, audio_path, "下载音频")
    
    except Exception as e:
        print(f"❌ 操作失败: {str(e)}")
